#include "CValue.h"

CValue::CValue(int irow, int icol){
    row = irow;
    col = icol;
    histSize[0] = 256;
    hranges[0] = 0.0;
    hranges[1] = 255.0;
    ranges[0] = hranges;
    channels[0] = 0;
}

CValue::CValue(int irow, int icol, float max_b, float max_c, float max_ba, float min_b, float min_c, float min_ba,float wei_b, float wei_c, float wei_ba){
    row = irow;
    col = icol;
    histSize[0] = 256;
    hranges[0] = 0.0;
    hranges[1] = 255.0;
    ranges[0] = hranges;
    channels[0] = 0;
    max_blur = max_b;
    max_balance = max_ba;
    max_contrast = max_c;
    min_blur = min_b;
    min_balance = min_ba;
    min_contrast = min_c;
    wei_blur = wei_b;
    wei_contrast= wei_c;
    wei_balance = wei_ba;
}

void CValue::load_img(Mat img){

    v_blur=0;
    v_balance = 0;
    v_contrast = 0;
    std::vector<Mat> BGR;
    split(img.clone(), BGR);
    BGR.at(0).copyTo(img_b);
    BGR.at(1).copyTo(img_g);
    BGR.at(2).copyTo(img_r);
    img.convertTo(img, CV_32F);
    //normalize(img, img, 0, 1, CV_MINMAX);
    cvtColor(img, img_gray, CV_BGR2GRAY);

    //Mat hist_path(256, 1, CV_8U);
    /*unsigned char* data = hist_path.ptr<unsigned char>(0);*/
    //for (int i = 0; i<256 ; ++i){
        //data[i] = i;
    /*}*/
    //cout<<hist_path<<endl;
}

void CValue::blur_value(){

    float k = 0.0;
    int nRows = row;
    int nCols = col;
    int u, v;
 /*   Mat dst;*/
    //Laplacian( img_gray, dst, CV_32F, 3, 1, 0, BORDER_DEFAULT);
    //normalize(dst, dst, 0, 1, CV_MINMAX);
    //imshow("lap", dst);

    //if(dst.isContinuous())
    //{
        //nCols *= row;
        //float* data = dst.ptr<float>(0);

        //for (int p = 0; p < nCols; ++p){
            //k += data[p];
           //}
    //}
    //else {
        //for (v = 1; v < nRows-1; ++v)
        //{
            //float* data = img_gray.ptr<float>(v);
            //for (u = 1; u < nCols-1; ++u)
            //{
              //k += data[u];
            //}
        //}
    //}
    /*v_blur = k/(row * col);*/
    //cout<<dst<<endl;
    //cout<<v_blur<<endl;

    if(img_gray.isContinuous())
    {
        nCols *= row;
        float* data = img_gray.ptr<float>(0);

        for (int p = 0; p < nCols; ++p){
            v = p / (img_gray.step/4);
            u = p % (img_gray.step/4);
            if(v>0 && v<row-1 && u>0 && u<col-1 )
                k += pow(data[v*img_gray.step/4 + u +1]-data[v*img_gray.step/4 + u], 2)
                +pow(data[v*img_gray.step/4 + u -1]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v+1)*img_gray.step/4 + u]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v-1)*img_gray.step/4 + u]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v+1)*img_gray.step/4 + u +1]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v+1)*img_gray.step/4 + u -1]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v-1)*img_gray.step/4 + u +1]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v-1)*img_gray.step/4 + u -1]-data[v*img_gray.step/4 + u], 2);
        }
    }
    else {
        for (v = 1; v < nRows-1; ++v)
        {
            float* data = img_gray.ptr<float>(v);
            for (u = 1; u < nCols-1; ++u)
            {
              k += pow(data[v*img_gray.step/4 + u +1]-data[v*img_gray.step/4 + u], 2)
                +pow(data[v*img_gray.step/4 + u -1]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v+1)*img_gray.step/4 + u]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v-1)*img_gray.step/4 + u]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v+1)*img_gray.step/4 + u +1]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v+1)*img_gray.step/4 + u -1]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v-1)*img_gray.step/4 + u +1]-data[v*img_gray.step/4 + u], 2)
                +pow(data[(v-1)*img_gray.step/4 + u -1]-data[v*img_gray.step/4 + u], 2);
            }
        }
    }
    v_blur = k/(8*(row-2)*(col-2) + 6*(2*(row-2)+2*(col-2)) + 4*3);
}

float get_vector_sum(Mat vec){

    float sum = 0;
    float* data = vec.ptr<float>(0);
    for(int i=0; i<vec.rows; ++i){
        sum += data[i];
    }
    return sum;
}

void CValue::hist_value(){

    Mat hist_b, hist_g, hist_r;
    float b_mean = 0;
    float g_mean = 0;
    float r_mean = 0;
    b_var = 0;
    g_var = 0;
    r_var = 0;
    calcHist(&img_b, 1, channels, Mat(), hist_b, 1, histSize, ranges);
    calcHist(&img_g, 1, channels, Mat(), hist_g, 1, histSize, ranges);
    calcHist(&img_r, 1, channels, Mat(), hist_r, 1, histSize, ranges);
    hist_b /= row*col;
    hist_g /= row*col;
    hist_r /= row*col;

    float* data_b = hist_b.ptr<float>(0);
    float* data_g = hist_g.ptr<float>(0);
    float* data_r = hist_r.ptr<float>(0);
    for (int i = 0; i<256; ++i){
        b_mean += data_b[i] * i;
        g_mean += data_g[i] * i;
        r_mean += data_r[i] * i;
    }
    for (int i=0; i<256; ++i){
        b_var += data_b[i] * abs(i-b_mean);
        g_var += data_g[i] * abs(i-g_mean);
        r_var += data_r[i] * abs(i-r_mean);
    }
    v_balance = abs(b_mean-g_mean) + abs(b_mean-r_mean) + abs(r_mean-g_mean);
    v_contrast = b_var + g_var + r_var;
}

float CValue::get_img_value(Mat img){

    float v_b;
    float v_c;
    float v_ba;

    this->load_img(img);
    this->blur_value();
    this->hist_value();
    //if((v_blur-min_blur)/ (max_blur-min_blur) < 0.7)
        //v_b = wei_blur*100*(0.04905 -0.05372*cos((v_blur-min_blur)/ (max_blur - min_blur)*1.79) + 0.5945*sin((v_blur-min_blur)/ (max_blur-min_blur)*1.79));
    //else v_b = wei_blur * 100 * 0.7;
    v_b = wei_blur *  (v_blur-min_blur)/ (max_blur-min_blur);
    v_c = wei_contrast*(v_contrast-min_contrast)/ (max_contrast-min_contrast);
    v_ba = wei_balance*(v_balance-min_balance)/ (max_balance-min_balance);
    //v_b = wei_blur * log(v_blur);
    //v_c = wei_contrast * log(v_contrast);
    //v_ba = wei_balance * log(v_balance);

    //if ((v_blur-min_blur)/ (max_blur-min_blur)>0.6)
        //v_b -= 10*(v_blur-min_blur)/ (max_blur-min_blur);
    return v_b * v_c / (1+v_ba);
}
float CValue::get_blur_value(Mat img){

    this->load_img(img);
    this->blur_value();

    return v_blur;
}

float CValue::get_contrast_value(Mat img){

    this->load_img(img);
    this->hist_value();

    return v_contrast;
}

vector<float> CValue::get_contrast_value(Mat img, bool flag){

    vector<float> cont;
    this->load_img(img);
    this->hist_value();
    cont.push_back(b_var);
    cont.push_back(g_var);
    cont.push_back(r_var);

    return cont;
}
float CValue::get_balance_value(Mat img){

    this->load_img(img);
    this->hist_value();

    return v_balance;
}

void CValue::sub_wei(int flag){

    switch (flag){
        case 0:
            wei_blur -= 0.01;
            break;
        case 1:
            wei_contrast -= 0.01;
            break;
        case 2:
            wei_balance -= 0.01;
            break;
        default:
            break;

    }
}


void CValue::add_wei(int flag){

    switch (flag){
        case 0:
            wei_blur += 0.01;
            break;
        case 1:
            wei_contrast += 0.01;
            break;
        case 2:
            wei_balance += 0.01;
            break;
        default:
            break;

    }
}
